package rep

import (
	"fmt"
	"strings"
	"testing"

	"gitcode.com/deyiyangyang/gascheme/ast"
	"gitcode.com/deyiyangyang/gascheme/lex"
	"gitcode.com/deyiyangyang/gascheme/par"
)

// TestNeedsMoreInput tests the needsMoreInput function
func TestNeedsMoreInput(t *testing.T) {
	// Test balanced parentheses
	testCases := []struct {
		input    string
		expected bool
	}{
		{"()", false},
		{"(1 2 3)", false},
		{"((", true},
		{"(()", true},
		{"(() )", false},
		{"(define x 5)", false},
		{"(define (f x)", true},
		{"(define (f x) (+ x 1))", false},
		{"(define (f x)\n  (+ x 1))", false},
		{"(define (f x)\n  (+ x 1)", true},
		{"(define (factorial n)\n    (if (= n 1)\n        1\n        (* n (factorial (- n 1)))))", false},
	}

	for _, tc := range testCases {
		result := needsMoreInput(tc.input)
		if result != tc.expected {
			t.Errorf("needsMoreInput(%q) = %v; expected %v", tc.input, result, tc.expected)
		}
	}
}

// TestMultilineInput tests multiline input handling
func TestMultilineInput(t *testing.T) {
	// Test cases with multiline input that should be properly handled
	multilineInputs := []string{
		"(define (square x)\n  (* x x))\n(square 5)",
		"(define (add x y)\n  (+ x y))\n(add 3 4)",
		"(define (factorial n)\n    (if (= n 1)\n        1\n        (* n (factorial (- n 1)))))\n(factorial 5)",
	}

	for _, input := range multilineInputs {
		// Just verify that the input doesn't cause parsing errors
		// We're primarily testing that the parentheses matching works correctly
		lines := strings.Split(input, "\n")
		var reconstructed strings.Builder
		for _, line := range lines {
			reconstructed.WriteString(line + "\n")
			if !needsMoreInput(reconstructed.String()) {
				// If we don't need more input, we've got a complete expression
				break
			}
		}

		// The final result should not need more input
		if needsMoreInput(reconstructed.String()) {
			t.Errorf("Multiline input should not need more input: %q", input)
		}
	}
}

func TestLoad(t *testing.T) {
	// Test cases with multiline input that should be properly handled
	input := `(load "hello.scm")`
	//input = "123"
	l := lex.NewLexer(input)
	p := par.NewParser(l)

	expr, err := p.ParseExpression()
	if err != nil {
		t.Fatalf("Error parsing integer literal: %s", err)
	}

	list, ok := expr.(*ast.ListExpression)
	if !ok {
		fmt.Println(list)
	} else {
		fmt.Println("yes!")
		fmt.Println(list.Elements[0].TokenLiteral())
		fmt.Println(list.Elements[1].TokenLiteral())
	}

}
